#include <defs.h>
#include <user.h>
#include <nameserver.h>
#include <string.h>
#include <bwio.h>
#include <ts7200.h>

void NsRecordInit(ns_record *ns, int tid, char *name) {
  ns->tid = tid;
  ns->accesses = 0;
  StringCopy(ns->name, name);
}

void NsRecordSwap(ns_record *ns1, ns_record *ns2) {
  ns_record temp = *ns1;
  *ns1 = *ns2;
  *ns2 = temp;
}

void NameServer() {
  // Name table
  ns_record names[MAX_TASKS];
  int num_names = 0;
	
	int i;
	name_req request;
	int sender_tid;
	int reply = 0xDEADBEEF;

	for (;;) {
    Receive(&sender_tid, (char*)&request, sizeof(name_req));
    
    // Search the table for a match
    for (i = 0; i < num_names; i++) {
      if (StringCompare(names[i].name, request.name, MAX_NAME_LEN)) {
        break;
      }
    }
    
    if (request.type == WHO_IS_REQUEST) {      
      if (i == num_names) {
        bwprintf(COM2, "Request: '%s'\r\n", request.name);
        for (i = 0; i < num_names; i++)
          bwprintf(COM2, "%d: id[%d]: '%s', found = %d\r\n", i, names[i].tid, names[i].name, StringCompare(names[i].name, request.name, MAX_NAME_LEN));        
        bwprintf(COM2, "Request: '%s'\r\n", request.name);
        reply = ERROR_TASK_NOT_FOUND;
      } else {
        reply = names[i].tid;
        names[i].accesses++;
        // optimization: sort by number of accesses
        // note that this does not actually sort; instead, it optionally
        // reverses one inversion. this way, the array is _gradually_ sorted
        // while guaranteeing O(1) accesses!
        //if (i > 0 && names[i].accesses > names[i-1].accesses) {
        //  NsRecordSwap( &(names[i]), &(names[i-1]) );
        //}
      }
    } else if (request.type == REGISTER_AS_REQUEST) {
      if (i == MAX_TASKS) {
        reply = ERROR_TABLE_FULL;
      } else {
        if (i < num_names) {
          names[i].tid = request.tid;
        } else {
          NsRecordInit( &(names[i]), request.tid, request.name );
          num_names++;
        }
        reply = SUCCESS;
      }
    }
    
    // Return the reply value to the sender
		Reply(sender_tid, (char*)&reply, sizeof(int));
	}
}
